package edu.udo.sopra10.chaturaji.gui;

import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JPanel;
import javax.swing.Timer;

import edu.udo.sopra10.chaturaji.events.EventListenerList;
import edu.udo.sopra10.chaturaji.gui.util.SimpleGridBagConstraints;

/**
 * Panel that displays two dice next to each other and offers animations to
 * change their values.
 * 
 * @author Patrick Westerhoff
 */
public class DicePanel extends JPanel implements ActionListener
{
	private static final long serialVersionUID = -5593111012397213513L;
	
	private EventListenerList<ActionListener> listeners = new EventListenerList<ActionListener>();
	private DiePanel die1;
	private DiePanel die2;
	private Timer timer;
	
	private int timerCount;
	private byte d1;
	private byte d2;
	
	/**
	 * Constructs a new DicePanel showing two dice.
	 * 
	 */
	public DicePanel ()
	{
		super( new GridBagLayout() );
		SimpleGridBagConstraints c = new SimpleGridBagConstraints();
		
		// dice
		die1 = new DiePanel();
		die2 = new DiePanel();
		
		this.setBackground( null );
		this.add( die1, c.setGrid( 0, 0 ) );
		this.add( die2, c.setGrid( 1, 0 ) );
		
		// initialize
		setValues( (byte) 1, (byte) 1 );
		
		// timer
		timer = new Timer( 0, this );
		timer.setDelay( 25 );
	}
	
	/**
	 * Sets the values of the displayed dice.
	 * 
	 * @param d1 side of first die.
	 * @param d2 side of second die.
	 */
	public void setValues ( byte d1, byte d2 )
	{
		die1.setDieValue( d1 );
		die2.setDieValue( d2 );
	}
	
	/**
	 * Animates the dice to display the new values.
	 * 
	 * @param d1 side of first die.
	 * @param d2 side of second die.
	 */
	public void rollTo ( int d1, int d2 )
	{
		this.d1 = (byte) d1;
		this.d2 = (byte) d2;
		this.timerCount = 20;
		timer.start();
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void actionPerformed ( ActionEvent event )
	{
		if ( timerCount-- <= 0 )
		{
			timer.stop();
			this.setValues( this.d1, this.d2 );
			this.processEvent( new ActionEvent( this, ActionEvent.ACTION_PERFORMED, "roll completed" ) );
			
			return;
		}
		
		byte rand1 = (byte) Math.ceil( Math.random() * 6 );
		byte rand2 = (byte) Math.ceil( Math.random() * 6 );
		
		this.setValues( rand1, rand2 );
	}
	
	/**
	 * Adds the ActionEvent listener.
	 * 
	 * @param eventListener event listener object.
	 */
	public void addActionListener ( final ActionListener eventListener )
	{
		listeners.addListener( eventListener );
	}
	
	/**
	 * Removes the ActionEvent listener.
	 * 
	 * @param eventListener event listener object.
	 */
	public void removeActionListener ( final ActionListener eventListener )
	{
		listeners.removeListener( eventListener );
	}
	
	/**
	 * Processes the ActionEvent and notifies all event listeners.
	 * 
	 * @param event the event object.
	 */
	public void processEvent ( final ActionEvent event )
	{
		for ( final ActionListener eventListener : listeners.getListeners() )
		{
			eventListener.actionPerformed( event );
		}
	}
}